# 导入 sys 模块，用于访问命令行参数，比如获取用户输入的文件名
import sys
# 导入 re 模块，用于使用正则表达式，这里主要是为了清理文本中的标点符号
import re

# 定义一个函数，名为 countFile，它接受两个参数：
# filename: 要读取的源文件名 (字符串)
# words: 一个字典，用来存储统计到的词频结果
def countFile(filename, words):
    # 使用 try...except 结构来捕获可能发生的错误，让程序更健壮
    try:
        # 尝试以只读模式("r")打开指定的文件，并明确使用 "utf-8" 编码
        # 这样可以确保正确处理包含中文字符或其他非英文字符的文件
        f = open(filename, "r", encoding="utf-8")
    except Exception as e:
        # 如果在打开文件时发生任何错误（比如文件不存在），
        # 就会执行这里的代码
        print(e)  # 打印错误信息，告诉用户发生了什么
        return 0  # 返回 0，作为一个信号，表示函数执行失败

    # 如果文件成功打开，就读取文件的全部内容，并存入变量 txt
    txt = f.read()
    # 读取完毕后，立即关闭文件，这是一个好习惯，可以释放系统资源
    f.close()

    # --- 核心文本处理部分 ---
    # 1. txt.lower(): 将所有文本转换成小写，以避免 "Hello" 和 "hello" 被当成两个不同的词
    # 2. re.sub(r"[^a-z\s]", " ", ...): 使用正则表达式进行替换。
    #    - r"[^a-z\s]" 这个模式匹配所有“不是小写字母(a-z)也不是空白符(\s)”的字符。
    #    - " ": 将所有匹配到的字符（也就是标点、数字等）替换成一个空格。
    #    - 最终结果 cleaned_txt 是一个只剩下小写单词和空格的干净字符串。
    cleaned_txt = re.sub(r"[^a-z\s]", " ", txt.lower())
    
    # 使用 split() 方法，根据空白符将干净的字符串分割成一个单词列表
    txt1 = cleaned_txt.split()
    
    # 遍历单词列表中的每一个单词 (x)
    for x in txt1:
        # 这是统计词频的核心技巧：
        # words.get(x, 0) 会尝试从字典中获取键为 x 的值。
        # - 如果 x 存在，就返回它当前的值（也就是它已经出现的次数）。
        # - 如果 x 不存在（即这个单词是第一次出现），就返回默认值 0。
        # 然后，将这个值加 1，并重新存入字典。
        words[x] = words.get(x, 0) + 1
    return 1

# --- 主程序从这里开始执行 ---

# 创建一个空字典，用来接收函数处理后的词频统计结果
result = {}

# 调用我们定义的函数，并传入命令行参数作为文件名
# sys.argv[1] 是用户在命令行输入的第一个参数（源文件名）
# result 是我们创建的空字典，它会被函数填充
# 如果函数返回 0（表示打开文件失败），if 条件成立
if countFile(sys.argv[1], result) == 0:
    # 退出程序
    exit()

# 将字典 result 转换成一个列表，列表中的每个元素都是一个 (键, 值) 的元组
# 例如：[('hello', 2), ('world', 1)]
lst = list(result.items())

# 对列表进行排序。因为元组默认会先按第一个元素（也就是单词）排序，
# 所以这里会自动按单词的字母顺序进行排序。
lst.sort()

# 以写入模式("w")打开命令行输入的第二个参数（结果文件名）
# 如果文件不存在，会自动创建；如果存在，会清空内容。
f = open(sys.argv[2], "w", encoding="utf-8")

# 遍历排好序的列表
for x in lst:
    # x 是一个元组，例如 ('hello', 2)
    # x[0] 是单词 'hello'
    # x[1] 是次数 2
    # 使用 f-string 格式化字符串，中间用制表符 \t 分隔，末尾加上换行符 \n
    f.write(f"{x[0]}\t{x[1]}\n")

# 所有内容写入完毕后，关闭文件
f.close()